<template>
	<view class="flex-justify-align-center">
		<view
			class="thermostat"
			:style="{ '--w': thermostat.width + 'rpx', '--h': thermostat.height + 'rpx', '--deg': tapData.deg + 'deg' }"
		>
			<view class="ticks">
				<view
					v-for="index in scaleNum"
					:key="index"
					class="tick"
					:style="{
						transform: `rotate(${index * (180 / (scaleNum - 1))}deg ) translate(0,-${
							thermostat.height / 2 + 10
						}rpx)`,
					}"
				>
					<view v-if="index % 10 === 0" class="relative">
						<text class="absolute text-grey" style="transform: translate(-6px, -20px)"
							>{{ index + initT }}°</text
						>
					</view>
				</view>
			</view>
			<view
				class="circle relative flex justify-center align-center"
				id="circle"
				@touchend="handleTouchEnd"
				@touchstart="handleLongPress"
				@touchmove.stop="handleTouchMove"
			>
				<view class="w-80 h-80 round circleShadow" style="z-index: 3">
					<view class="h-100 flex flex-direction relative justify-center align-center margin-top">
						<view class="pointer absolute"></view>
						<view class="status text-lg text-grey text-bold">{{ title }}</view>
						<view class="temperature text-xxl" style="color: #cfd0d4; font-size: 65rpx"
							>{{ getText }} <text class="text-lg" style="vertical-align: top">°C</text></view
						>
						<image
							@tap="handleLeaf"
							src="../../static/leaf.png"
							style="width: 44rpx; height: 44rpx"
							mode="aspectFit"
						></image>
					</view>
				</view>
				<LcircularProgress
					class="absolute"
					style="top: -8%; left: -8%; z-index: 2"
					:percent="tapData.percentVal"
					:lineWidth="canvasProps.lineWidth"
					:boxWidth="canvasProps.width"
					:boxHeight="canvasProps.height"
					progressColor="#7881a9"
					gradualColor="#5b5c7a"
				/>
			</view>
		</view>
	</view>
</template>

<script>
	import LcircularProgress from '@/compoments/l-circularProgress/l-circularProgress.vue';
	import { throttle } from '@/common/util.js';
	const winWidth = uni.getSystemInfoSync().windowWidth;
	const degMap = new Map();
	const percentMap = new Map();

	export default {
		components: { LcircularProgress },
		props: {
			width: {
				type: Number,
				default: 400,
				required: true,
			},
			height: {
				type: Number,
				default: 400,
				required: true,
			},
			title: {
				type: String,
				default: 'COOLING',
			},
			// 刻度数量
			scaleNum: {
				type: Number,
				default: 21,
				required: true,
			},

			// 是否保留小数
			showDot: {
				type: Boolean,
				default: true,
			},
			// 保留小数点增加的倍数
			step: {
				type: Number,
				default: 0.5,
				validator: function (val) {
					return val > 0 && val <= 1;
				},
			},
			// 初始温度 10
			initT: {
				type: Number,
				default: 10,
			},
			// 当前温度
			currentT: {
				type: Number,
				required: true,
			},
		},
		data() {
			return {
				// 整个扭动器的大小
				thermostat: {
					width: 0,
					height: 0,
				},
				// 要达到效果图的圆环最高百分比
				allPercent: 82.3,
				percent: 52,
				initPercentVal: 16,
				// 刻度的数量
				// 单个刻度占比
				scalePercent: 0,
				// canvas大小，无需修改，填入上方thermostat数据自适应
				canvasProps: {
					width: 0,
					height: 0,
					lineWidth: 10,
				},
				// 当前最高温度
				maxT: 0,
				isLong: false,
				// 按下时收集的数据
				tapData: {
					// 顺时针还是逆时针
					direct: 0,
					// 起点
					start: {
						x: 0,
						y: 0,
					},
					// 圆心
					circleCenter: {
						x: 0,
						y: 0,
					},
					// 当前进度条值
					percentVal: 0,
					// 当前旋转角度
					deg: 0,
				},
			};
		},

		computed: {
			// 当前度数
			getText() {
				const percentVal = this.tapData.percentVal;
				if (percentMap.get(this.maxT) <= percentVal) {
					return this.maxT;
				}
				let result = null;
				percentMap.forEach((value, key) => {
					if (percentVal === value) {
						result = key;
					}
				});
				return result;
			},
		},
		watch: {
			'tapData.percentVal'(val, oldv) {
				if (val - this.initPercentVal < 0) {
					this.tapData.percentVal = this.initPercentVal;
				}
				const current = this.getText;
				this.tapData.deg = degMap.get(current) || this.getCurrentDeg(current);
			},
		},
		created() {
			// 每个刻度所占比
			this.scalePercent = this.percent / this.scaleNum;
			// 当前最高温度
			this.maxT = this.scaleNum - 1 + this.initT;

			// 初始化进度条
			this.tapData.percentVal = this.initPercentVal;
			this.thermostat.width = this.width;
			this.thermostat.height = this.height;
			this.canvasProps.width = ((this.thermostat.width / 750) * winWidth) / 1.14;
			this.canvasProps.height = ((this.thermostat.height / 750) * winWidth) / 1.14;
			this.canvasProps.lineWidth = ((this.thermostat.width / 750) * winWidth) / 25;
			this.handlePrecent();
		},
		mounted() {
			const query = uni.createSelectorQuery().in(this);
			query
				.select('#circle')
				.boundingClientRect(data => {
					// 算出当前按钮的圆心
					this.tapData.circleCenter.y = data.top + data.height / 2;
					this.tapData.circleCenter.x = data.left + data.width / 2;
				})
				.exec();
			if (this.currentT) {
				if (this.currentT > this.maxT) {
					throw Error('所传入的props:currentT超出当前最高温度');
				}
				if (this.currentT < this.initT) {
					throw Error('所传入的props:currentT小于当前最低温度');
				}
				this.tapData.percentVal = percentMap.get(this.currentT);
			}
		},
		methods: {
			// 获取当前温度对应的角度
			getCurrentDeg(val) {
				let result;
				if (val === this.initT) {
					result = 0;
				} else {
					result = (val - this.initT) * +this.scalePercent.toFixed(2) * Math.PI;
				}
				const data = Math.floor(result);
				degMap.set(val, data);
				return data;
			},
			getCurrentPrecent(val) {
				if (percentMap.get(val)) {
					return percentMap.get(val);
				}
				let result = null;
				if (val === this.initT) {
					result = this.initPercentVal;
				} else {
					result = (val - this.initT) * this.scalePercent + this.initPercentVal;
				}
				return result;
			},
			// 处理所有温度的对应进度条值
			handlePrecent() {
				for (let i = this.initT; i <= this.maxT; ) {
					const result = this.getCurrentPrecent(i);
					percentMap.set(i, result);
					if (this.showDot) {
						i += this.step;
					} else {
						i++;
					}
				}
			},
			handleLeaf() {
				this.$emit('leaf');
			},
			handleLongPress(e) {
				this.tapData.start.x = e.changedTouches[0].clientX;
				this.tapData.start.y = e.changedTouches[0].clientY;
				this.isLong = true;
			},
			handleTouchMove: throttle(function (e) {
				if (!this.isLong) return;

				const x = e.changedTouches[0].clientX;
				const y = e.changedTouches[0].clientY;

				const AB = {};
				const AC = {};
				AB.x = this.tapData.start.x - this.tapData.circleCenter.x;
				AB.y = this.tapData.start.y - this.tapData.circleCenter.y;
				AC.x = x - this.tapData.circleCenter.x;
				AC.y = y - this.tapData.circleCenter.y;
				const direct = AB.x * AC.y - AB.y * AC.x; // AB与AC叉乘求出逆时针还是顺时针旋转
				const lengthAB = Math.sqrt(
						Math.pow(this.tapData.circleCenter.x - this.tapData.start.x, 2) +
							Math.pow(this.tapData.circleCenter.y - this.tapData.start.y, 2),
					),
					lengthAC = Math.sqrt(
						Math.pow(this.tapData.circleCenter.x - x, 2) + Math.pow(this.tapData.circleCenter.y - y, 2),
					),
					lengthBC = Math.sqrt(Math.pow(this.tapData.start.x - x, 2) + Math.pow(this.tapData.start.y - y, 2));
				const cosA =
					(Math.pow(lengthAB, 2) + Math.pow(lengthAC, 2) - Math.pow(lengthBC, 2)) / (2 * lengthAB * lengthAC); //   余弦定理求出旋转角
				const angleA = Math.round((Math.acos(cosA) * 180) / Math.PI);

				this.tapData.start.x = x;
				this.tapData.start.y = y;
				if (direct < 0) {
					// 初始值
					if (this.tapData.percentVal - this.initPercentVal <= 0) {
						this.tapData.percentVal = this.initPercentVal;
						return;
					}
					// 从满值回退时
					if (this.tapData.percentVal >= this.allPercent) {
						this.tapData.percentVal = percentMap.get(Number(this.getText));
						return;
					}
					// 根据角度算进度条
					// this.tapData.percentVal -= (angleA * 0.4) / this.scalePercent;
					// 根据step来算进度条
					const text = this.showDot ? +this.getText - this.step : +this.getText - 1;
					this.tapData.percentVal = percentMap.get(text);

					//叉乘结果为负表示逆时针旋转， 逆时针旋转减度数
				} else {
					// 当前值大于最大值则为最大值
					if (this.getText >= this.maxT) {
						this.tapData.percentVal = this.allPercent;
						return;
					}
					const text = this.showDot ? +this.getText + this.step : +this.getText + 1;
					// 根据角度算进度条
					// this.tapData.percentVal += (angleA * 0.4) / this.scalePercent;
					// 根据step来算进度条
					this.tapData.percentVal = percentMap.get(text);

					//叉乘结果为正表示顺时针旋转，顺时针旋转加度数
				}
				// this.isLong = false;
			}, 40),
			handleTouchEnd(e) {
				this.isLong = false;
				this.handleEmitTouchEnd();
				// if (this.isLong) return;
				// this.tapData.start.x = e.changedTouches[0].clientX;
				// this.tapData.start.y = e.changedTouches[0].clientY;
				// if (this.tapData.direct < 0) {
				// 	// 初始值
				// 	if (this.tapData.percentVal - this.initPercentVal <= 0) {
				// 		this.tapData.percentVal = this.initPercentVal;
				// 		return;
				// 	}
				// 	// 从满值回退时
				// 	if (this.tapData.percentVal >= this.allPercent) {
				// 		this.tapData.percentVal = percentMap.get(this.getText);
				// 		return;
				// 	}
				// 	this.tapData.percentVal -= this.scalePercent;
				// 	//叉乘结果为负表示逆时针旋转， 逆时针旋转减度数
				// } else {
				// 	// 当前值大于最大值则为最大值
				// 	if (this.getText === this.maxT) {
				// 		this.tapData.percentVal = this.allPercent;
				// 		return;
				// 	}
				// 	this.tapData.percentVal += this.scalePercent;
				// 	//叉乘结果为正表示顺时针旋转，顺时针旋转加度数
				// }
			},
			handleEmitTouchEnd() {
				this.$emit('end', { deg: this.tapData.deg, percent: this.tapData.percentVal });
			},
		},
	};
</script>

<style scoped lang="scss">
	.thermostat {
		position: relative;
		width: var(--w);
		height: var(--h);
		border-radius: 50%;
		background-color: #d5dae4;
		display: flex;
		align-items: center;
		justify-content: center;
		flex-direction: column;
		box-shadow: #d5dae4 6rpx 6rpx 10rpx 0, #ffffff 6rpx 6rpx 10rpx 0;
	}
	.ticks {
		position: absolute;
		width: 100%;
		height: 100%;
		border-radius: 50%;
		transform: rotate(-90deg);
	}

	.tick {
		position: absolute;
		width: 2px;
		height: 5%;
		left: 50%;
		bottom: 50%;
		background-color: #c7c8cd;
		transform: translate(-5%, -5%);
		transform-origin: bottom;
	}
	.circle {
		width: 75%;
		height: 75%;
		border-radius: 50%;
		background-color: #f1f2f6;
	}
	.circleShadow {
		// transform: rotate(var(--deg));
		will-change: transform;
		border-radius: 50%;
		background: linear-gradient(145deg, #f1f1f1, #ffffff);
		box-shadow: 50rpx 50rpx 124rpx #e9e9e9, -50rpx -50rpx 124rpx #ffffff;
	}
	.progress {
		width: 40rpx;
		height: 40rpx;
		background-color: red;
		border-radius: 10rpx;
	}
	.pointer {
		position: absolute;
		transform: rotate(var(--deg)) translate(-24rpx, 32%);
		width: 78%;
		height: 78%;
		&::before {
			content: '';
			display: block;
			width: 20rpx;
			height: 20rpx;
			border-radius: 50px;
			transform-origin: left top;
			background: linear-gradient(145deg, #dddddd, #ffffff);
			box-shadow: 2px 2px 3px #e9e9e9, -2px -2px 3px #ffffff;
		}
	}

	.status {
	}
</style>
